import { Response } from 'express';
import prisma from '../lib/prisma';
import type { TransactionClient } from '../types/prisma-types';
import { UserRole } from '../types/prisma-types';
import { AuthenticatedRequest } from '../types/auth';
import { UserService } from '../services/userService';
import { StatusCodes } from '../constants/statusCodes';
import { logger } from '../utils/logger';
import { ApiError } from '../utils/ApiError';

type CreateUserData = {
  email: string;
  password: string;
  name: string;
  role: UserRole;
};

export const userController = {
  async getUsers(req: AuthenticatedRequest, res: Response) {
  },
  async assignUserRole(req: AuthenticatedRequest, res: Response) {
    // 分配用户角色的实现
    const { userId, role } = req.body;
    // 假设有一个 UserService 来处理用户相关的业务逻辑
    await UserService.assignRole(userId, role);
    res.status(200).json({ message: '角色分配成功' });
  },
  },
  async assignUserRole(req: AuthenticatedRequest, res: Response) {
    // 分配用户角色的实现
    const { userId, role } = req.body;
    // 假设有一个 UserService 来处理用户相关的业务逻辑
    await UserService.assignRole(userId, role);
    res.status(200).json({ message: '角色分配成功' });
  },
  },
  async assignUserRole(req: AuthenticatedRequest, res: Response) {
    // 分配用户角色的实现
    const { userId, role } = req.body;
    // 假设有一个 UserService 来处理用户相关的业务逻辑
    await UserService.assignRole(userId, role);
    res.status(200).json({ message: '角色分配成功' });
  },
  },
  async assignUserRole(req: AuthenticatedRequest, res: Response) {
    // 分配用户角色的实现
    const { userId, role } = req.body;
    // 假设有一个 UserService 来处理用户相关的业务逻辑
    await UserService.assignRole(userId, role);
    res.status(200).json({ message: '角色分配成功' });
  },
  },
  async assignUserRole(req: AuthenticatedRequest, res: Response) {
    // 分配用户角色的实现
    const { userId, role } = req.body;
    // 假设有一个 UserService 来处理用户相关的业务逻辑
    await UserService.assignRole(userId, role);
    res.status(200).json({ message: '角色分配成功' });
  },
  },
  async assignUserRole(req: AuthenticatedRequest, res: Response) {
    // 分配用户角色的实现
    const { userId, role } = req.body;
    // 假设有一个 UserService 来处理用户相关的业务逻辑
    await UserService.assignRole(userId, role);
    res.status(200).json({ message: '角色分配成功' });
  },
  },
  async assignUserRole(req: AuthenticatedRequest, res: Response) {
    // 分配用户角色的实现
    const { userId, role } = req.body;
    // 假设有一个 UserService 来处理用户相关的业务逻辑
    await UserService.assignRole(userId, role);
    res.status(200).json({ message: '角色分配成功' });
  },
  },
  async assignUserRole(req: AuthenticatedRequest, res: Response) {
    // 分配用户角色的实现
    const { userId, role } = req.body;
    // 假设有一个 UserService 来处理用户相关的业务逻辑
    await UserService.assignRole(userId, role);
    res.status(200).json({ message: '角色分配成功' });
  },
  async assignUserRole(req: AuthenticatedRequest, res: Response) {
    // 分配用户角色的实现
    const { userId, role } = req.body;
    // 假设有一个 UserService 来处理用户相关的业务逻辑
    await UserService.assignRole(userId, role);
    res.status(200).json({ message: '角色分配成功' });
  }
    const page = parseInt(req.query.page as string) || 1;
    const limit = parseInt(req.query.limit as string) || 10;
    const searchQuery = req.query.search as string;
    const roleFilter = req.query.role as UserRole;

    const where = {
      AND: [
        searchQuery
          ? {
              OR: [
                { name: { contains: searchQuery, mode: 'insensitive' } },
                { email: { contains: searchQuery, mode: 'insensitive' } },
              ],
            }
          : {},
        roleFilter ? { role: roleFilter } : {},
      ],
    };

    const result = await prisma.$transaction(async (tx: TransactionClient) => {
      const users = await tx.user.findMany({
        where,
        select: {
          id: true,
          name: true,
          email: true,
          role: true,
          createdAt: true,
          updatedAt: true,
        },
        skip: (page - 1) * limit,
        take: limit,
        orderBy: { createdAt: 'desc' },
      });
      const total = await tx.user.count({ where });
      return { users, total };
    });

    logger.info('Retrieved users list', { page, limit, total: result.total });

    res.json({
      items: result.users,
      total: result.total,
      page,
      pages: Math.ceil(result.total / limit),
    });
  },

  async getUserById(req: AuthenticatedRequest, res: Response) {
    const user = await prisma.user.findUnique({
      where: { id: req.params.id },
      select: {
        id: true,
        name: true,
        email: true,
        role: true,
        createdAt: true,
        updatedAt: true,
      },
    });

    if (!user) {
      throw new ApiError(StatusCodes.NOT_FOUND, 'User not found');
    }

    logger.info('Retrieved user by ID', { userId: req.params.id });
    res.json(user);
  },

  async createUser(req: AuthenticatedRequest, res: Response) {
    const { email, password, name, role } = req.body as CreateUserData;

    const existingUser = await prisma.user.findUnique({ where: { email } });
    if (existingUser) {
      throw new ApiError(StatusCodes.CONFLICT, 'User already exists');
    }

    const user = await prisma.user.create({
      data: {
        email,
        password,
        name,
        role,
      },
      select: {
        id: true,
        name: true,
        email: true,
        role: true,
        createdAt: true,
      },
    });

    logger.info('Created new user', { userId: user.id });
    res.status(StatusCodes.CREATED).json(user);
  },

  async resetPassword(req: AuthenticatedRequest, res: Response) {
    const { id } = req.params;
    const { newPassword } = req.body;

    try {
      const user = await prisma.user.update({
        where: { id },
        data: { password: newPassword },
        select: {
          id: true,
          name: true,
          email: true,
          role: true,
          createdAt: true,
          updatedAt: true,
        },
      });

      logger.info('Password reset for user', { userId: id });
      res.json({ message: 'Password reset successfully', user });
    } catch (error) {
      logger.error('Error resetting password', { error, userId: id });
      if (error && typeof error === 'object' && 'code' in error && error.code === 'P2025') {
        throw new ApiError(StatusCodes.NOT_FOUND, 'User not found');
      }
      throw new ApiError(StatusCodes.INTERNAL_SERVER_ERROR, 'An unexpected error occurred');
    }
  },

  async updateUser(req: AuthenticatedRequest, res: Response) {
    const { id } = req.params;
    const updates = req.body;

    if (updates.email) {
      const existingUser = await prisma.user.findFirst({
        where: {
          email: updates.email,
          NOT: { id },
        },
      });
      if (existingUser) {
        throw new ApiError(StatusCodes.CONFLICT, 'Email already in use');
      }
    }

    try {
      const user = await prisma.user.update({
        where: { id },
        data: updates,
        select: {
          id: true,
          name: true,
          email: true,
          role: true,
          createdAt: true,
          updatedAt: true,
        },
      });

      logger.info('Updated user', { userId: id });
      res.json(user);
    } catch (error) {
      logger.error('Error updating user', { error, userId: id });
      if (error && typeof error === 'object' && 'code' in error && error.code === 'P2025') {
        throw new ApiError(StatusCodes.NOT_FOUND, 'User not found');
      }
      throw new ApiError(StatusCodes.INTERNAL_SERVER_ERROR, 'An unexpected error occurred');
    }
  },

  async deleteUser(req: AuthenticatedRequest, res: Response) {
    const { id } = req.params;

    try {
      await prisma.user.delete({ where: { id } });
      logger.info('Deleted user', { userId: id });
      res.status(StatusCodes.NO_CONTENT).send();
    } catch (error) {
      logger.error('Error deleting user', { error, userId: id });
      if (error && typeof error === 'object' && 'code' in error && error.code === 'P2025') {
        throw new ApiError(StatusCodes.NOT_FOUND, 'User not found');
      }
      throw new ApiError(StatusCodes.INTERNAL_SERVER_ERROR, 'An unexpected error occurred');
    }
  },

  async updateManyUsers(req: AuthenticatedRequest, res: Response) {
    const { userIds, data } = req.body;

    await prisma.$transaction(async (tx: TransactionClient) => {
      for (const id of userIds) {
        await tx.user.update({
          where: { id },
          data,
        });
      }
    });

    logger.info('Batch updated users', { userIds, updates: data });
    res.json({ message: 'Users updated successfully' });
  },

  async searchUsers(req: AuthenticatedRequest, res: Response) {
    const { query = '', limit = 10 } = req.query;
    const users = await prisma.user.findMany({
      where: {
        OR: [
          { name: { contains: query as string, mode: 'insensitive' } },
          { email: { contains: query as string, mode: 'insensitive' } },
        ],
      },
      select: {
        id: true,
        name: true,
        email: true,
        role: true,
      },
      take: Number(limit),
    });

    logger.info('Searched users', { query, limit, results: users.length });
    res.json(users);
  },
};
